#include <iostream>
#include <memory>
#include <functional>
#include <vector>
#include <unordered_map>
#include <unistd.h>
using FuncTask = std::function<void()>;
using ReleaseTask = std::function<void()>;
class TimerTask
{
public:
    TimerTask(uint64_t fd, uint32_t timeout, FuncTask func)
        : _fd(fd), _timeout(timeout), _func(func), _canceled(false)
    {
    }
    ~TimerTask()
    {
        if (!_canceled)
        {
            _func();//定时器要执行的任务
        }
         _release();
    }
    void SetRelease(ReleaseTask release)
    {
        _release = release;
    }
    uint32_t GetTimeout()
    {
        return _timeout;
    }
    void SetCannel()
    {
        _canceled = true;
    }

private:
    uint64_t _fd;         // 定时器标识fd
    uint32_t _timeout;    // 超时时间
    bool _canceled;       // fasle表示不取消任务，true表示取消任务
    FuncTask _func;       // 定时器过期执行的任务
    ReleaseTask _release; // 删除TimerWheel中的定时器信息
};

class TimerWheel
{
public:
    using WeakTask = std::weak_ptr<TimerTask>;
    using PtrTask = std::shared_ptr<TimerTask>;

private:
    void RemoveTask(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it != _timers.end())
        {
            _timers.erase(it);
        }
    }

public:
    TimerWheel()
        : _tick(0), _capacity(60), _wheel(_capacity)
    {
    }
    ~TimerWheel()
    {
    }

    void AddTimerTask(uint64_t id, uint32_t timeout, FuncTask func)
    {
        PtrTask pt(new TimerTask(id, timeout, func));
        pt->SetRelease(std::bind(&TimerWheel::RemoveTask, this, id));
        int pos = (_tick + timeout) % _capacity;
        _wheel[pos].push_back(pt);
        WeakTask wt = pt;
        _timers[id] = wt;
    }

    void RefreshTask(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it == _timers.end())
        {
            return; // 定时器任务不存在，刷新不了
        }
        PtrTask pt = it->second.lock(); // lock是weak_ptr second的shared_ptr
        int pos = (_tick + pt->GetTimeout()) % _capacity;
        _wheel[pos].push_back(pt);
    }

    void Run()
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear(); // 清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
    }

    void CannelTask(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it == _timers.end())
        {
            return;
        }
        PtrTask pt = it->second.lock();
        if (pt)
            pt->SetCannel();
    }

private:
    std::vector<std::vector<PtrTask>> _wheel; // 时间轮
    int _tick;                                // 模拟秒针，走到那里执行哪里的任务
    int _capacity;                            // 最大延迟时间
    std::unordered_map<uint64_t, WeakTask> _timers;
};
class Test
{
public:
    Test()
    {
        std::cout << "构造" << std::endl;
    }
    ~Test()
    {
        std::cout << "析构" << std::endl;
    }
};
void Delete(Test *t)
{
    delete t;
}

int main()
{
    TimerWheel wheel;
    Test *t = new Test();
    wheel.AddTimerTask(888, 5, std::bind(Delete, t));

    for (int i = 0; i < 5; i++)
    {
        std::cout << "任务推迟到5s以后执行" << std::endl;
        wheel.RefreshTask(888);
        wheel.Run();
        sleep(1);
    }
    wheel.CannelTask(888);
    while (1)
    {
        std::cout << "----------------" << std::endl;
        wheel.Run();
        sleep(1);
    }
}